package cn.wolfcode.business.service.impl;

import cn.wolfcode.business.domain.BusAppointment;
import cn.wolfcode.business.domain.BusStatement;
import cn.wolfcode.business.domain.BusStatementItem;
import cn.wolfcode.business.domain.vo.StatementItemVo;
import cn.wolfcode.business.mapper.BusStatementItemMapper;
import cn.wolfcode.business.service.IBusAppointmentService;
import cn.wolfcode.business.service.IBusStatementItemService;
import cn.wolfcode.business.service.IBusStatementService;
import cn.wolfcode.common.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * 结算单明细Service业务层处理
 * 
 * @author wolfcode
 * @date 2025-08-22
 */
@Service
public class BusStatementItemServiceImpl implements IBusStatementItemService 
{
    @Autowired
    private BusStatementItemMapper busStatementItemMapper; // 结算单明细 Mapper

    @Autowired
    private IBusStatementService statementService; // 结算单 Service

    @Autowired
    private IBusAppointmentService appointmentService;  // 预约单 Service

    /**
     * 查询结算单明细
     * 
     * @param id 结算单明细主键
     * @return 结算单明细
     */
    @Override
    public BusStatementItem selectBusStatementItemById(Long id)
    {
        return busStatementItemMapper.selectBusStatementItemById(id);
    }

    /**
     * 查询结算单明细列表
     * 
     * @param busStatementItem 结算单明细
     * @return 结算单明细
     */
    @Override
    public List<BusStatementItem> selectBusStatementItemList(BusStatementItem busStatementItem)
    {
        return busStatementItemMapper.selectBusStatementItemList(busStatementItem);
    }

    /**
     * 新增结算单明细
     * 
     * @param busStatementItem 结算单明细
     * @return 结果
     */
    @Override
    public int insertBusStatementItem(BusStatementItem busStatementItem)
    {
        return busStatementItemMapper.insertBusStatementItem(busStatementItem);
    }

    /**
     * 修改结算单明细
     * 
     * @param busStatementItem 结算单明细
     * @return 结果
     */
    @Override
    public int updateBusStatementItem(BusStatementItem busStatementItem)
    {
        return busStatementItemMapper.updateBusStatementItem(busStatementItem);
    }

    /**
     * 批量删除结算单明细
     * 
     * @param ids 需要删除的结算单明细主键
     * @return 结果
     */
    @Override
    public int deleteBusStatementItemByIds(Long[] ids)
    {
        return busStatementItemMapper.deleteBusStatementItemByIds(ids);
    }

    /**
     * 删除结算单明细信息
     * 
     * @param id 结算单明细主键
     * @return 结果
     */
    @Override
    public int deleteBusStatementItemById(Long id)
    {
        return busStatementItemMapper.deleteBusStatementItemById(id);
    }

    /**
     * 新增结算单明细数据 && 更新结算单数据
     * @param vo
     * @return
     */
    @Override
    //- 需要添加十五 @Transactional 注解。
    @Transactional
    public int saveItem(StatementItemVo vo) {
        //- 对参数合理化校验。
        if(vo == null){
            throw new RuntimeException("非法参数");
        }
        if(vo.getStatementItemList() == null || vo.getStatementItemList().size() == 0
                || vo.getDiscountAmount() == null){
            throw new RuntimeException("非法参数");
        }
        List<BusStatementItem> statementItemList = vo.getStatementItemList();
        BigDecimal discountAmount = vo.getDiscountAmount();
        //- 从结算单明细列表集合中任何获取一条数据中的结算单 id 即可（因为多条结算单明细都对应了同一个结算单）。
        Long statementId = statementItemList.get(0).getStatementId();
        if (statementId == null) {
            throw new RuntimeException("非法参数");
        }
        //- 根据结算单 ID 查询结算单状态。判断状态必须是消费中才可以进行保存操作。（验证）
        BusStatement statement = statementService.selectBusStatementById(statementId);
        if (statement == null) {
            throw new RuntimeException("非法参数");
        }
        if(BusStatement.STATUS_PAID.equals(statement.getStatus())){
            throw new RuntimeException("已支付的结算单禁止保存操作");
        }
        // 追加判断，已删除的结算单禁止保存
        if(BusStatement.IS_DELETE.equals(statement.getIsDelete())){
            throw new RuntimeException("已删除的结算单禁止保存操作");
        }
        // 当验证结束后，我们需要将所有之前结算单明细数据都删除掉，在重新插入新的即可。
        busStatementItemMapper.deleteRelationStatementItemBuStatementId(statementId);
        //- 遍历结算单明细集合。计算出总金额、总数量。
        // 总金额
        BigDecimal totalAmount = BigDecimal.ZERO;
        // 总数量
        BigDecimal totalQuantity = BigDecimal.ZERO;
        for (BusStatementItem serviceItem : statementItemList) {
            if(serviceItem.getItemPrice() == null || serviceItem.getItemQuantity() == null){
                throw new RuntimeException("非法参数");
            }
            // 计算总金额  totalAmount += xxx + xxx     totalAmount = totalAmount + (xxx + xxx)
            totalAmount =
                    totalAmount.add(serviceItem.getItemPrice().multiply(new BigDecimal(serviceItem.getItemQuantity())));
            // 计算总数量   totalQuantity = totalQuantity + new BigDecimal(serviceItem.getItemQuantity())
            totalQuantity =  totalQuantity.add(new BigDecimal(serviceItem.getItemQuantity()));
        }
        //- 对金额进行验证（总金额 > 0，总数量 >= 1, 折扣价 >=0 && 折扣价 <= 总金额）
        if(totalAmount.compareTo(new BigDecimal("0")) < 0 || totalQuantity.compareTo(new BigDecimal("0")) < 0
            || discountAmount.compareTo(new BigDecimal("0")) < 0 || totalAmount.compareTo(discountAmount) < 0){
            throw new RuntimeException("总金额、总数量、折扣价都必须大于0，且总价格需要大于等于折扣价");
        }
        //- 批量插入结算单明细
        busStatementItemMapper.insertBusStatementItemBatch(statementItemList);
        //- 更新结算单 总金额，总数量，折扣金额。
        return statementService.updateAmount(statementId,totalAmount,totalQuantity,discountAmount);
    }

    /**
     * 支付功能
     * @param statementId
     * @return
     */
    @Override
    @Transactional
    public int pay(Long statementId) {
        // 1. 参数合理化验证。
        if (statementId == null) {
            throw new RuntimeException("非法参数");
        }
        // 根据传入的结算单 id 查询结算单对象
        BusStatement statement = statementService.selectBusStatementById(statementId);
        if (statement == null) {
            throw new RuntimeException("非法参数");
        }
        // 2. 验证必须是消费中的结算单才可以进行支付操作。
        if(BusStatement.STATUS_PAID.equals(statement.getStatus())){
            throw new RuntimeException("已支付的结算单禁止重复支付");
        }
        // 该结算单不为无效状态
        if(BusStatement.IS_DELETE.equals(statement.getIsDelete())){
            throw new RuntimeException("已删除的结算单禁止支付");
        }
        // 3. 需要将结算单的状态  消费中 -->  已支付。同时加入收款人和收款时间。（更新状态及收款人和收款时间）。
        // 获取收款人 id
        Long payId = SecurityUtils.getUserId();
        int statementCount = statementService.updatePayStatusById(statementId,payId,new Date(),BusStatement.STATUS_PAID);
        // 4. 若当前用户是预约用户，
        if(statement.getAppointmentId() != null){
            // 则需要将预约单中的状态更新为已支付。（前提是关联了预约单）。
            int appCount = appointmentService.updateStatus(statement.getAppointmentId(), BusAppointment.STATUS_PAID);
            statementCount = (statementCount > 0 && appCount > 0)  ? 1 :  0;
        }

        // 5. 添加事务
        return statementCount;
    }
}
